package org.raymond.iworks.admin.config;

import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.sql.DataSource;

@Configuration
public class DatasourceConfiguration {

    @Bean
    public DataSource dataSource(){
        HikariConfig config = new HikariConfig();
        config.setJdbcUrl("jdbc:p6spy:mysql://localhost:3306/iworks?allowPublicKeyRetrieval=true" +
                "&characterEncoding=UTF-8" +
                "&useUnicode=true" +
                "&useSSL=false" +
                "&tinyInt1isBit=false" +
                "&allowPublicKeyRetrieval=true" +
                "&serverTimezone=Asia/Shanghai" +
                "&allowMultiQueries=true" +
                "&rewriteBatchedStatements=true" +
                "&connectTimeout=15000" +
                "&socketTimeout=60000");
        config.setUsername("iworks");
        config.setPassword("iworks123");
        // config.setDriverClassName("com.mysql.cj.jdbc.Driver");
        config.setDriverClassName("com.p6spy.engine.spy.P6SpyDriver");
        // 连接返回连接池时,是否自动提交事务
        config.setAutoCommit(true);
        // 从连接池获取连接的最大超时时间,默认为 30000ms=30s,允许最小时间是250毫秒,如果小于250毫秒,则被重置回30秒
        config.setConnectionTimeout(30*1000);
        /**
         * 连接允许在池中闲置的最长时间,默认为600000,即10分钟.
         * 如果idleTimeout+1秒>maxLifetime且maxLifetime>0,则会被重置为0(代表永远不会退出);
         * 如果idleTimeout!=0且小于10秒,则会被重置为10秒.
         * 只有当minimumIdle小于maximumPoolSize时,这个参数才生效,
         * 当空闲连接数超过minimumIdle,而且空闲时间超过idleTimeout,则会被移除.
         */
        config.setIdleTimeout(60*1000);
        /**
         * 连接存活时间,这个值必须小于maxLifetime值."Keepalive"只会发生在空闲的连接上.
         * 当对一个给定的连接进行"keepalive"的时间到了,该连接将从池中移除.
         * 允许的最小值是30000ms（30秒）,但最理想的值是在分钟范围内.默认值:0,表示不检测
         */
        config.setKeepaliveTime(0);
        /**
         * 池中连接最长生命周期.默认为1800000,如果不等于0且小于30秒则会被重置回30分钟.
         * 0表示没有限制.强烈建议设置这个参数
         */
        config.setMaxLifetime(30*60*1000);
        /**
         * 控制连接池空闲连接的最小数量.
         * 当连接池空闲连接少于minimumIdle,而且总共连接数不大于maximumPoolSize时,HikariCP会尽力补充新的连接.
         * 为了性能考虑,不建议设置此值,而是让HikariCP把连接池当做固定大小的处理,默认minimumIdle与maximumPoolSize一样.
         * 当minIdle<0或者minIdle>maxPoolSize,则被重置为maxPoolSize,该值默认为 10
         */
        config.setMinimumIdle(10);
        /**
         * 池中最大连接数,包括闲置和使用中的连接.默认为10.
         * 如果maxPoolSize小于1,则会被重置.
         * 当minIdle<=0被重置为DEFAULT_POOL_SIZE则为10;
         * 如果minIdle>0,则重置为minIdle的值
         */
        config.setMaximumPoolSize(10);
        /**
         * 连接池的用户定义名称,主要出现在日志记录和JMX管理控制台中以识别池和池配置.默认为HikariPool-1
         */
        config.setPoolName("HikariPool-1");
        /**
         * 从池中获取的连接是否默认处于只读模式.默认为false.这个属性工作与否取决于数据库的实现
         */
        config.setReadOnly(false);
        /**
         * 如果你的驱动程序支持JDBC4,我们强烈建议不要设置这个属性.这是针对不支持JDBC4 Connection.isValid() API的"传统"驱动程序.
         * 这是一个查询,在一个连接从池子里给你之前会被执行,以验证与数据库的连接是否仍然有效.
         * 同样,尝试在没有这个属性的情况下运行数据库池,如果你的驱动不符合JDBC4标准,HikariCP会记录一个错误,让你知道.默认值:无
         */
        config.setConnectionTestQuery(null);

        config.setConnectionInitSql("select 1");
        /**
         * 启动连接池时不能成功初始化连接,是否快速失败.
         * >0时,会尝试获取连接.如果获取时间超过指定时长(connectionTimeout + initializationFailTimeout),不会开启连接池,并抛出异常.
         * =0时,会尝试获取并验证连接.如果获取成功但验证失败则不开启池,但是如果获取失败还是会开启池.
         * <0时,直接启动连接池,不进行初始化连接尝试.
         */
        config.setInitializationFailTimeout(1);
        // 是否在事务中隔离HikariCP自己的查询;autoCommit为false时,该设置生效
        config.setIsolateInternalQueries(false);
        // 是否允许通过JMX挂起和恢复连接池;挂起时获取连接不会超时,直到连接池恢复
        config.setAllowPoolSuspension(false);
        // 默认的事务隔离级别,默认为驱动配置
        //config.setTransactionIsolation("");
        // 连接检测的超时时间;必须大于connectionTimeout,最小允许的值为 250
        config.setValidationTimeout(5000);
        // 连接可以被借出多久;超过该时间将打印连接可能泄露的日志,最小允许的值为2000,单位 ms
        config.setLeakDetectionThreshold(0);
        // 指定数据源.此参数仅通过编程配置或IoC容器可用,当设置此参数,dataSourceClassName和所有DataSource-相关的属性将被忽略
        //config.setDataSource(null);
        //config.setThreadFactory(null);
        // 指定连接池用于执行定时任务的java.util.concurrent.ScheduledExecutorService实例.此参数仅通过编程配置或IoC容器可用
        //config.setScheduledExecutor(null);
        HikariDataSource ds = new HikariDataSource(config);
        return ds;
    }

}
